package com.zhanghu.backendZray.serializer;

import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.ContextualSerializer;

import java.lang.annotation.Annotation;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.math.RoundingMode;

/**
 * @param <A>         自定义的序列化注解
 * @param <FieldType> 序列化的字段类型
 */
public abstract class BaseJKAnnotationSerializer<A extends Annotation, FieldType> extends JsonSerializer<FieldType> implements ContextualSerializer {

    /**
     * 自定义的注解
     */
    protected A annotation;

    /**
     * 序列化的字段类型
     */
    protected Class<?> fieldClass;

    /**
     * 动态决定序列化的方式，以及获取序列化的上下文，比如要序列化的字段的信息等等
     */
    @Override
    public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property) throws JsonMappingException {
        // 子类获取父亲标记的泛型参数
        Class<A> acls = getFatherParamType();

        annotation = property.getAnnotation(acls);
        this.fieldClass = property.getType().getRawClass();

        if (annotation == null || !isFilterSerializer(property)) {
            return prov.findValueSerializer(property.getType(), property);
        }
        return this;
    }

    /**
     * 判断此字段是否需要使用此序列化器
     */
    protected boolean isFilterSerializer(BeanProperty property) {
        return true;
    }

    private Class<A> getFatherParamType() {
        Type superclass = getClass().getGenericSuperclass();
        Class<A> acls = null;
        if (superclass instanceof ParameterizedType) {
            ParameterizedType parameterizedType = (ParameterizedType) superclass;
            Type actualTypeArgument = parameterizedType.getActualTypeArguments()[0];
            acls = (Class<A>) actualTypeArgument;
        }
        return acls;
    }

    public static String smartScale(BigDecimal olBValue, int scale) {
        if (olBValue == null) {
            return "";
        }

        if (olBValue.compareTo(BigDecimal.ZERO) == 0) {
            return "0";
        }

        BigDecimal bValue = olBValue.setScale(scale, RoundingMode.HALF_UP);
        for (int i = scale + 1; i <= 8; i++) {
            if (bValue.compareTo(BigDecimal.ZERO) != 0) {
                break;
            }
            bValue = olBValue.setScale(i, RoundingMode.HALF_UP);
        }

        return bValue.toString();
    }
}
